﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace CPPEI.ETL.DSImplement
{
    static class PropertyInjection
    {
        public static void Injection(Type type, object obj, string rootPath, Dictionary<string, object> valueDict)
        {
            InjectProperties(type, obj, rootPath, valueDict);

            InjectFields(type, obj, rootPath, valueDict);
        }
        
        private static void InjectProperties(Type type, object obj, string rootPath, Dictionary<string, object> valueDict)
        {
            #region 注入属性
            PropertyInfo[] props = type.GetProperties();
            for (int index = 0; index < props.Length; index++)
            {
                PropertyInfo propertyInfo = props[index];

                string fullPath = null;

                if (string.IsNullOrEmpty(rootPath))
                {
                    fullPath = props[index].Name;
                }
                else
                {
                    fullPath = string.Format("{0}.{1}", rootPath, props[index].Name);
                }

                if (props[index].PropertyType.IsClass)
                {
                    // 又是一个复杂类型

                    object propertyObject = propertyInfo.PropertyType.Assembly.CreateInstance(propertyInfo.PropertyType.FullName);

                    Injection(propertyInfo.PropertyType, propertyObject, fullPath, valueDict);
                }
                else
                {
                    object propValue = null;
                    foreach (var valueKey in valueDict.Keys)
                    {
                        if (string.Equals(valueKey, fullPath))
                        {
                            propValue = valueDict[valueKey];
                            valueDict.Remove(valueKey);
                            break;
                        }
                    }

                    props[index].SetValue(obj, propValue);
                }
            }
            #endregion
        }

        private static void InjectFields(Type type, object obj, string rootPath, Dictionary<string, object> valueDict)
        {
            FieldInfo[] props = type.GetFields();
            for (int index = 0; index < props.Length; index++)
            {
                FieldInfo propertyInfo = props[index];

                string fullPath = null;

                if (string.IsNullOrEmpty(rootPath))
                {
                    fullPath = props[index].Name;
                }
                else
                {
                    fullPath = string.Format("{0}.{1}", rootPath, props[index].Name);
                }

                if (props[index].FieldType.IsClass && props[index].FieldType != typeof(string))
                {
                    // 又是一个复杂类型

                    object propertyObject = propertyInfo.FieldType.Assembly.CreateInstance(propertyInfo.FieldType.FullName);

                    Injection(propertyInfo.FieldType, propertyObject, fullPath, valueDict);
                }
                else
                {
                    object propValue = null;
                    foreach (var valueKey in valueDict.Keys)
                    {
                        if (string.Equals(valueKey, fullPath))
                        {
                            propValue = valueDict[valueKey];
                            valueDict.Remove(valueKey);
                            break;
                        }
                    }

                    props[index].SetValue(obj, propValue);
                }
            }
        }
    }
}
